﻿using AppSocketModel;
using AppSocketService.Account; 
using BCGPSCommon;
using BCGPSMongoData;
using LJD.IMS.Utility;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Text;

namespace AppSocketService.Location
{
    /// <summary>
    /// 车辆位置
    /// </summary>
    public class LocationService : ServiceBase, ILocationService
    {
        #region var
        // 账户车辆位置表前缀
        private readonly string AccountVehicleLocationCollation = "AccountVehicleLocation";

        private MongoDBCommand<LocationDto> mongoCommand = null;

        private readonly IRedisService redisService;
        private readonly AccountDto CurrentAccount;
        private readonly IAccountService accountService;
        private readonly GCJ02_WGS84_TransTools gCJ02_WGS84_TransTools = new GCJ02_WGS84_TransTools();
        #endregion

        #region 构造
        public LocationService(IClaimsAccessor claimsAccessor, IRedisService redisService, IAccountService accountService) : base(claimsAccessor)
        {
            this.redisService = redisService;
            this.accountService = accountService;
            CurrentAccount = accountService.GetCurrentAccount();
            mongoCommand = new MongoDBCommand<LocationDto>(AccountVehicleLocationCollation);
        }

        //只在 初始化 Redis 用
        public LocationService(IRedisService redisService)
        {
            mongoCommand = new MongoDBCommand<LocationDto>(AccountVehicleLocationCollation);
            this.redisService = redisService;
        }
        #endregion


        #region  初始化REDIS用 获取全部位置列表
        public List<LocationDto> InitRedisGetListAll()
        {
            return mongoCommand.SelectDocumentsAsync(s=>s.IMEI!=null).GetAwaiter().GetResult();
        }
        #endregion

        #region 添加一个车辆
        public LocationDto AddNew(LocationDto locationDto)
        {
            if (string.IsNullOrWhiteSpace(locationDto.IMEI))
                throw new ArgumentException("IMEI必须填写!");

            var dto = mongoCommand.SelectDocumentAsync(s => s.CompanyId == locationDto.CompanyId && s.IMEI == locationDto.IMEI).GetAwaiter().GetResult();

            if (dto != null)
            {
                mongoCommand.DeleteDocumentAsync(s => s.CompanyId == CurrentAccount.CompanyId && s.IMEI == locationDto.IMEI).GetAwaiter().GetResult();
            }
            mongoCommand.InsertDocumentAsync(locationDto).GetAwaiter().GetResult();
            return locationDto;


        }
        #endregion

        #region 修改车辆 IMEI
        public LocationDto UpdateImei(string vehicleNo, string Imei)
        {  
                var update = Builders<LocationDto>.Update
                    .Set(s => s.VehicleNo , vehicleNo);
                return mongoCommand.UpdateDocumentAsync(s =>s.CompanyId==CurrentAccount.CompanyId && s.IMEI == Imei, update).GetAwaiter().GetResult();  
        }
        #endregion

        #region 更新位置信息
        public void UpdateGpsInfo(GpsInfoDto gpsInfoDto)
        {
            var update = Builders<LocationDto>.Update
                .Set(s => s.GpsTime, gpsInfoDto.GpsTime)
                .Set(s => s.SysTime, gpsInfoDto.SysTime)
                .Set(s => s.Lat, gpsInfoDto.Lat)
                .Set(s => s.Lng, gpsInfoDto.Lng)
                .Set(s=>s.Speed,gpsInfoDto.Speed)
                .Set(s => s.Course, gpsInfoDto.Course);
            mongoCommand.UpdateDocumentAsync(s => s.IMEI == gpsInfoDto.Imei, update).GetAwaiter().GetResult();
        }
        #endregion

        #region 删除车辆位置记录
        public int Delete(VehicleDto vehicleDto)
        {
            return (int)mongoCommand.DeleteDocumentAsync(s => s.CompanyId == CurrentAccount.CompanyId && s.IMEI == vehicleDto.IMEI).GetAwaiter().GetResult().DeletedCount;
        }
        #endregion

        #region 获取指定公司全部定位记录
        public List<LocationDto> GetAll(int companyId)
        {
            return mongoCommand.SelectDocumentsAsync(s => s.CompanyId == companyId).GetAwaiter().GetResult();
        }
        #endregion

        #region 获取IMEI定位信息
        public LocationDto GetLocation(string imei, GpsMapType gpsMapType)
        {
            LocationDto ret = redisService.Get<LocationDto>(GeneralContainer.RedisNameSpaceIMEILocation + imei);
            if (ret == null)
            {
                ret = mongoCommand.SelectDocumentAsync(s => s.CompanyId == CurrentAccount.CompanyId && s.IMEI == imei).GetAwaiter().GetResult();
            }
            if (ret != null)
            {
                LocateInfo info;

                if (ret.Location == LocationType.LBS.ToString())
                {
                    info = new LocateInfo();
                    switch (gpsMapType)
                    {
                        case GpsMapType.GDMAP:
                            ret.Lat = ret.Lat;
                            ret.Lng = ret.Lng;
                            break;
                        case GpsMapType.BAIDUMAP:
                            info = gCJ02_WGS84_TransTools.Gcj02_To_bd09(ret.Lat, ret.Lng);
                            ret.Lat = info.Latitude;
                            ret.Lng = info.longitude;
                            break;
                    }

                }
                else
                {
                    switch (gpsMapType)
                    {
                        case GpsMapType.GDMAP:
                            info = gCJ02_WGS84_TransTools.wgs84_To_Gcj02(ret.Lat, ret.Lng);
                            ret.Lat = info.Latitude;
                            ret.Lng = info.longitude;
                            break;
                        case GpsMapType.BAIDUMAP:
                            info = gCJ02_WGS84_TransTools.wgs84_To_Bd09(ret.Lat, ret.Lng);
                            ret.Lat = info.Latitude;
                            ret.Lng = info.longitude;
                            break;
                    }
                }
                if (ret.GpsTime.HasValue)
                {
                    TimeSpan span = DateTime.Now - ret.GpsTime.Value;
                    if (span.TotalSeconds > 60)
                    {
                        ret.GpsDeviceOnlineState = GpsDeviceOnlineState.OFFLINE;
                        ret.OffLineTime = new OffLineTimeDto();
                        ret.OffLineTime.Days = span.Days;
                        ret.OffLineTime.Hours = span.Hours;
                        ret.OffLineTime.Minutes = span.Minutes;
                        ret.GpsDeviceSpeedState = null;
                    }
                    else
                    {
                        ret.GpsDeviceOnlineState = GpsDeviceOnlineState.ONLINE;
                        if (ret.Speed > 0.01)
                            ret.GpsDeviceSpeedState = GpsDeviceSpeedState.RUN;
                        else
                            ret.GpsDeviceSpeedState = GpsDeviceSpeedState.STOP;
                        ret.OffLineTime = null;
                    }
                }
                else
                {
                    ret.GpsDeviceOnlineState = GpsDeviceOnlineState.OFFLINE;
                    ret.GpsDeviceSpeedState = null;
                    ret.OffLineTime = null;
                }
            }
            return ret; 
        }
        #endregion 

        #region 获取指定账户定位信息 不包括子账户
        public List<LocationDto> GetList(string accountId, GpsMapType gpsMapType)
        {
            var list = mongoCommand.SelectDocumentsAsync(s => s.CompanyId == CurrentAccount.CompanyId && s.AccountId == accountId).GetAwaiter().GetResult();
            List<LocationDto> retList = new List<LocationDto>();
            foreach (var item in list)
            {  
                try
                {
                    var dto = GetLocation(item.IMEI, gpsMapType);
                    if(dto!=null)
                        retList.Add(dto);
                }
                catch ( Exception ex)
                {
                    var msg = ex.Message;
                }
            }
            return retList;
        }
        #endregion

        #region 获取指定账户定位信息 包括子账户
        public List<LocationDto> GetListAll(string accountId, GpsMapType gpsMapType)
        {
            var accountlist = accountService.GetSubAccountIdAll(accountId);

            List<LocationDto> retList = new List<LocationDto>();

            foreach (var item in accountlist)
            {
                var list = GetList(item, gpsMapType);
                if (list != null && list.Count > 0)
                    retList.AddRange(list);
            }
            return retList; 
        }
        #endregion

        #region 设置车辆归属账户
        public LocationDto SetVehicleAccount(string imei,string accountId)
        {
            var update = Builders<LocationDto>.Update
                .Set(s => s.AccountId, accountId);
            var a = mongoCommand.UpdateDocumentAsync(s =>s.CompanyId == CurrentAccount.CompanyId && s.IMEI == imei, update).GetAwaiter().GetResult();
            return a;
        }
        #endregion
    }
}
